home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / macros / latex209 / contrib / textyl / src / tyl.c < prev   
C/C++ Source or Header  |  1993-11-07  |  41KB  |  1,510 lines

  1. #include    "defs.h"
  2. #include    "globals.h"
  3.  
  4. static ScaledPts dviBBlx, dviBBrx;    /* Bounding box of figure in DVI space */
  5. static ScaledPts dviBBby, dviBBty;
  6. static int32    prevfont;
  7. /*
  8.  * to keep track of prev font before the PUSH and expansion of the special
  9.  */
  10. static int32    ourpushdepth = 0;    /* depth of internal pushes */
  11. static int32    origTexfont = -1;    /* number of TeX font in use before tyling */
  12.  
  13. static void 
  14. IPUSH()
  15. {
  16.     if (ourpushdepth == 0)    /* first push --> start tyling */
  17.         origTexfont = font[curfont].num;
  18.     else
  19.         prevfont = ourfontnum;
  20.     /* store the internal font number in use at this time */
  21.     cmd1byte(NOP);
  22.     cmd1byte(NOP);        /* our greeting */
  23.     cmd1byte(PUSH);
  24.     ourpushdepth++;
  25. }
  26.  
  27. static void 
  28. IPOP()
  29. {
  30.     cmd1byte(POP);
  31.     cmd1byte(NOP);
  32.     cmd1byte(NOP);        /* our signature */
  33.     ourpushdepth--;
  34.     if (ourpushdepth < 0)
  35.     {
  36.         complain(ERRREALBAD);
  37.         fprintf(logfile, "Error: too many internal pops\n");
  38.     }
  39.     if (ourpushdepth == 0)
  40.     {            /* we are totally done with tyling for now */
  41.         if (nf > 0)    /* only if it is valid */
  42.             isetfont(origTexfont);
  43.     }
  44.     else
  45.     {
  46.         if (prevfont >= 0)    /* restore that internal font previously in use */
  47.             isetfont(prevfont);
  48.     }
  49. }
  50.  
  51. char           *
  52. xmalloc(size)
  53.     unsigned int    size;
  54. {
  55.     char           *p;
  56.     char           *malloc PP((unsigned));
  57.     void        exit PP((int));
  58.  
  59.     if ((p = malloc(size)) == 0)
  60.     {
  61.         fprintf(stderr, "Out of memory!\n");
  62.         exit(1);
  63.     }
  64.     return (p);
  65. }
  66.  
  67. /*---------------------------------------------*/
  68. Item           *
  69. NewItem(what)
  70.     int             what;
  71. {
  72.     Item           *i;
  73.     Figure         *f;
  74.  
  75.     if ((i = (Item *) xmalloc(sizeof(Item))) == 0)
  76.         i->nextitem = NULL;
  77.     i->BBlx = 0;
  78.     i->BBby = 0;
  79.     i->BBrx = 0;
  80.     i->BBty = 0;
  81.     i->itemthick = LoVThick;
  82.     i->itemvec = (unsigned) VKCirc;
  83.     i->itempatt = (unsigned) solid;
  84.     i->kind = what;
  85.     switch (what)
  86.     {            /* give defaults */
  87.  
  88.     case Aline:
  89.         /* blank case */
  90.         break;
  91.  
  92.     case Aspline:
  93.         i->UU.U2.nsplknots = 0;
  94.         i->UU.U2.dosmarks = 0;
  95.         i->UU.U2.sclosed = false;
  96.         i->UU.U2.spltype = (unsigned) BSPL;
  97.         break;
  98.  
  99.     case Attspline:
  100.         i->UU.U3.nttknots = 0;
  101.         i->UU.U3.dottmarks = 0;
  102.         i->UU.U3.tspltype = (unsigned) BSPL;
  103.         i->UU.U3.tclosed = false;
  104.         break;
  105.  
  106.     case Abeam:
  107.         /* blank case */
  108.         break;
  109.  
  110.     case Atieslur:
  111.         i->UU.U5.ntknots = 0;
  112.         break;
  113.  
  114.     case Aarc:
  115.         i->UU.U6.narcknots = 0;
  116.         break;
  117.  
  118.     case Alabel:
  119.         i->UU.U7.fontstyle = -1;    /* undefined */
  120.         i->UU.U7.labeltext[0] = '\0';
  121.         break;
  122.  
  123.     case Afigure:
  124.         i->UU.U8.figtheta = 0.0;
  125.         i->UU.U8.fsx = 1.0;
  126.         i->UU.U8.fsy = 1.0;
  127.         i->UU.U8.fdx = 0;
  128.         i->UU.U8.fdy = 0;
  129.         i->UU.U8.preWid = 0;
  130.         i->UU.U8.preHt = 0;
  131.         i->UU.U8.postWid = 0;
  132.         i->UU.U8.postHt = 0;
  133.         i->UU.U8.depthnumber = 0;    /* for now */
  134.         f = (Figure *) xmalloc(sizeof(Figure));    /* a new figure */
  135.         i->UU.U8.body = f;
  136.         i->UU.U8.body->things = NULL;
  137.         break;
  138.     }            /* case */
  139.     /* with */
  140.     return i;
  141. }                /* NewItem */
  142.  
  143. /*-----------------------------------------------------*/
  144. static void 
  145. TylBeam(fromx, fromy, tox, toy, staffsize, kind)
  146.     int32           fromx, fromy, tox, toy, staffsize;
  147.     BeamKind        kind;
  148. {
  149.     /*
  150.      * fromx, fromy, tox, toy: ScaledPts; staffsize : integer; kind : BeamKind
  151.      */
  152. }                /* TylBeam */
  153.  
  154.  
  155. /* Local variables for TylLine: */
  156. struct LOC_TylLine
  157. {
  158.     VThickness      thickness;
  159. };
  160.  
  161.  
  162. /*-------------------------------------------------------*/
  163. static void 
  164. TylLine(xl, yb, xr, yt, thickness_, vec, patt)
  165.     int32           xl, yb, xr, yt;
  166.     VThickness      thickness_;
  167.     VectKind        vec;
  168.     LineStyle       patt;
  169. {
  170.     /*
  171.      * xl, yb, xr, yt: ScaledPoints; thickness: VThickness; vec: VectKind; patt : LineStyle
  172.      */
  173.     struct LOC_TylLine V;
  174.     VecIndex        findex;
  175.  
  176.     V.thickness = thickness_;
  177.     /*
  178.      * p2c: x.p, line 6596: Note: Taking & of possibly promoted param thickness [324]
  179.      */
  180.     clampthickness(&V.thickness);
  181.     findex = GetVectFont(V.thickness, vec);
  182.     layline(xl, yb, xr, yt, findex, patt, false);
  183. }
  184.  
  185. /*-----------------------------------------------------*/
  186. static void 
  187. TylThickThinSpline(thetype, isclosed, KnotArray, ThikThinAry,
  188.            numknots, vec, patt, domarks)
  189.     SplineKind      thetype;
  190.     int        isclosed;
  191. int32(*KnotArray)[2];
  192.     VThickness     *ThikThinAry;
  193.     int32           numknots;
  194.     VectKind        vec;
  195.     LineStyle       patt;
  196.     int32           domarks;
  197. {
  198.     /*
  199.      * thetype : SplineKind; isclosed : boolean; var KnotArray: ControlPoints; var ThikThinAry: ThickAryType; numknots:
  200.      * integer; vec: VectKind; patt : LineStyle; domarks : integer
  201.      */
  202.     layNspline(thetype, isclosed, false, domarks, KnotArray, numknots,
  203.            ThikThinAry, vec, patt);
  204. }
  205.  
  206. /*----------------------------------------------------*/
  207. static void 
  208. TylSpline(thetype, isclosed, KnotArray, numknots, thick, vec,
  209.       patt, domarks)
  210.     SplineKind      thetype;
  211.     int        isclosed;
  212. int32(*KnotArray)[2];
  213.     int32           numknots;
  214.     VThickness      thick;
  215.     VectKind        vec;
  216.     LineStyle       patt;
  217.     int32           domarks;
  218. {
  219.     /*
  220.      * thetype : SplineKind; isclosed : boolean; var KnotArray: ControlPoints; numknots: integer; thick: VThickness; vec:
  221.      * VectKind; patt : LineStyle; domarks : integer
  222.      */
  223.     layAspline(thetype, isclosed, false, domarks, KnotArray, numknots, thick,
  224.            vec, patt);
  225. }
  226.  
  227. #define ItsASlur        true
  228. #define NotClosed       false
  229.  
  230.  
  231. /* Local variables for TylTieSlur: */
  232. struct LOC_TylTieSlur
  233. {
  234.     VThickness      minthick, maxthick;
  235. };
  236.  
  237.  
  238. /*-----------------------------------------------------*/
  239. static void 
  240. TylTieSlur(KnotArray, numknots, minthick_, maxthick_)
  241. int32(*KnotArray)[2];
  242.     int32           numknots;
  243.     VThickness      minthick_, maxthick_;
  244. {
  245.     /*
  246.      * KnotArray: ControlPoints; numknots: integer; minthick, maxthick: VThickness
  247.      */
  248.     struct LOC_TylTieSlur V;
  249.     ThickAryType    ourttarray;
  250.     double          one7th;
  251.     VThickness      val;
  252.  
  253.     V.minthick = minthick_;
  254.     V.maxthick = maxthick_;
  255.     /*
  256.      * p2c: x.p, line 6636: Note: Taking & of possibly promoted param minthick [324]
  257.      */
  258.     clampthickness(&V.minthick);
  259.     /*
  260.      * p2c: x.p, line 6637: Note: Taking & of possibly promoted param maxthick [324]
  261.      */
  262.     clampthickness(&V.maxthick);
  263.     if (numknots != 5)
  264.         fprintf(logfile, "TieSlur needs 5 control points\n");
  265.     one7th = 1.0 / 7.0;
  266.     val = (int32) floor(one7th * (V.maxthick - V.minthick) + 0.5);
  267.     ourttarray[1] = V.minthick;
  268.     ourttarray[2] = V.minthick + val;
  269.     ourttarray[3] = V.maxthick;
  270.     ourttarray[4] = V.minthick + val;
  271.     ourttarray[5] = V.minthick;
  272.  
  273.     layNspline(CATROM, NotClosed, ItsASlur, 0, KnotArray, numknots, ourttarray,
  274.            VKCirc, solid);
  275. }
  276.  
  277. #undef ItsASlur
  278. #undef NotClosed
  279.  
  280.  
  281. #define ItsAnArc        true
  282.  
  283.  
  284. /*-------------------------------------------------------*/
  285. static void 
  286. doTylArc(iscircle, apts, numknots, thick, vec, patt)
  287.     int        iscircle;
  288. int32(*apts)[2];
  289.     int32           numknots;
  290.     VThickness      thick;
  291.     VectKind        vec;
  292.     LineStyle       patt;
  293. {
  294.     /*
  295.      * iscircle : boolean; var apts : ControlPoints; numknots : integer; thick : VThickness; vec : VectKind; patt :
  296.      * LineStyle
  297.      */
  298.     layAspline(BSPL, iscircle, ItsAnArc, 0, apts, numknots, thick, vec, patt);
  299. }
  300.  
  301. #undef ItsAnArc
  302.  
  303.  
  304. /*-----------------------------------------------------------*/
  305. static void 
  306. TylArc(radius, centx, centy, firstangle, secondangle, thick, vec,
  307.        patt)
  308.     int32           radius, centx, centy, firstangle, secondangle;
  309.     VThickness      thick;
  310.     VectKind        vec;
  311.     LineStyle       patt;
  312. {
  313.     /*
  314.      * radius : ScaledPts; centx, centy : ScaledPts; firstangle, secondangle : integer; thick : VThickness; vec : VectKind;
  315.      * patt : LineStyle
  316.      */
  317.     ControlPoints   apts;
  318.     int32           numknots;
  319.     int        iscircle;
  320.  
  321.     iscircle = (firstangle == secondangle);
  322.     if (iscircle)
  323.     {
  324.         /*
  325.          * maxspan := round ((360.0 / 16.0) * DEGTORAD * radius); {
  326.          */
  327.         defineCircleCpts(radius, centx, centy, apts, &numknots);
  328.     }
  329.     else
  330.     {
  331.         /*
  332.          * maxspan := round ((abs (secondangle - firstangle) / 16.0) * DEGTORAD * radius); {
  333.          */
  334.         definearcpts(radius, centx, centy, firstangle, secondangle, apts,
  335.                  &numknots);
  336.     }
  337.  
  338.     doTylArc(iscircle, apts, numknots, thick, vec, patt);
  339.  
  340. }
  341.  
  342.  
  343. /*-----------------------------------------------------------*/
  344. static void 
  345. TylLabel(xpos, ypos, fontstyle, phrase, phraselen)
  346.     int32           xpos, ypos, fontstyle;
  347.     char           *phrase;
  348.     int32           phraselen;
  349. {
  350.     /*
  351.      * xpos, ypos : ScaledPts; fontstyle : integer; phrase : charstring; phraselen : integer
  352.      */
  353.     int32           findex, c, spaceover;
  354.  
  355.     if (fontstyle < 1 || fontstyle > MAXLABELFONTS)
  356.     {
  357.         complain(ERRREALBAD);
  358.         fprintf(logfile, "Unexpected bad fontstyle in TylLabel: %d?\n",
  359.             fontstyle);
  360.         jumpout();
  361.     }
  362.     findex = GetLabFont(fontstyle);
  363.     isetpos(xpos, ypos);
  364.     IPUSH();
  365.     isetfont(LFontTable[findex - 1]->DVIFontNum);
  366.     spaceover = LFontTable[findex - 1]->spacewidth;
  367.     for (c = 0; c < phraselen; c++)
  368.     {
  369.         if (phrase[c] != ' ')
  370.         {
  371.             cmd1byte(SET1);
  372.             cmd1byte(phrase[c]);
  373.         }
  374.         else
  375.         {        /* move over */
  376.             cmd1byte(RIGHTLEFT + 2);
  377.             /* assume distance is less than 3 bytes */
  378.             cmdSigned(spaceover, 3);
  379.         }
  380.     }
  381.     IPOP();
  382. }
  383.  
  384. /* &&module TeXtyl */
  385. /*----------------------------------------------------------------*/
  386. /* rotate a (x,y) point about mx, my */
  387. static void 
  388. ptrotate(x, y, mx, my, angle)
  389.     int32          *x, *y, mx, my;
  390.     double          angle;
  391. {
  392.     int32           tmpx, tmpy;
  393.     double          cosa, sina;
  394.  
  395.     tmpx = *x - mx;
  396.     tmpy = *y - my;
  397.     cosa = cos(angle * DEGTORAD);
  398.     sina = sin(angle * DEGTORAD);
  399.     *x = (int32) floor(tmpx * cosa - tmpy * sina + 0.5) + mx;
  400.     *y = (int32) floor(tmpx * sina + tmpy * cosa + 0.5) + my;
  401. }
  402.  
  403.  
  404. /*----------------------------------------------------------------*/
  405. /*
  406.  * transform two line points: scale, rotate and translate
  407.  */
  408. static void 
  409. xfmlinepts(x1, y1, x2, y2, offh, offv, midx, midy, scalefact,
  410.        theta, dx, dy, sx, sy)
  411.     int32          *x1, *y1, *x2, *y2, offh, offv, midx, midy;
  412.     double          scalefact, theta;
  413.     int32           dx, dy;
  414.     double          sx, sy;
  415. {
  416.     if (sx == 0.0 || sy == 0.0)
  417.     {
  418.         complain(ERRBAD);
  419.         fprintf(logfile, "?? Some scale factor is Zero... continuing anyway\n");
  420.     }
  421.     /* scale about center of item */
  422.     if (sx != 1.0 || sy != 1.0)
  423.     {
  424.         *x1 = (int32) floor((*x1 - midx) * sx + 0.5) + midx;
  425.         *x2 = (int32) floor((*x2 - midx) * sx + 0.5) + midx;
  426.         *y1 = (int32) floor((*y1 - midy) * sy + 0.5) + midy;
  427.         *y2 = (int32) floor((*y2 - midy) * sy + 0.5) + midy;
  428.     }
  429.     /* rotate if necessary */
  430.     if (theta != 0.0)
  431.     {            /* rotate about the midpoint */
  432.         ptrotate(x1, y1, midx, midy, theta);
  433.         ptrotate(x2, y2, midx, midy, theta);
  434.     }
  435.     /* translate */
  436.     *x1 += (int32) floor(dx * scalefact + 0.5) + offh;
  437.     *x2 += (int32) floor(dx * scalefact + 0.5) + offh;
  438.     *y1 += (int32) floor(dy * scalefact + 0.5) + offv;
  439.     *y2 += (int32) floor(dy * scalefact + 0.5) + offv;
  440. }                /* xfmlinepts */
  441.  
  442.  
  443. /*----------------------------------------------------------------*/
  444. static void 
  445. xfmcontpts(xpts, xknots, offh, offv, midx, midy, scalefact, theta,
  446.        dx, dy, sx, sy)
  447. int32(*xpts)[2];
  448.     int32           xknots, offh, offv, midx, midy;
  449.     double          scalefact, theta;
  450.     int32           dx, dy;
  451.     double          sx, sy;
  452. {
  453.     int32           i;
  454.  
  455.     /* scale about center of item */
  456.     if (sx != 1.0 || sy != 1.0)
  457.     {
  458.         for (i = 0; i <= xknots; i++)
  459.         {
  460.             xpts[i][0] = (int32) floor((xpts[i][0] - midx) * sx + 0.5) + midx;
  461.             xpts[i][1] = (int32) floor((xpts[i][1] - midy) * sy + 0.5) + midy;
  462.         }
  463.     }
  464.  
  465.     if (theta != 0.0)
  466.     {            /* rotate about center */
  467.         for (i = 0; i <= xknots; i++)
  468.             ptrotate(xpts[i], &xpts[i][1], midx, midy, theta);
  469.     }
  470.     /* translate */
  471.     for (i = 0; i <= xknots; i++)
  472.     {
  473.         xpts[i][0] += (int32) floor(dx * scalefact + 0.5) + offh;
  474.         xpts[i][1] += (int32) floor(dy * scalefact + 0.5) + offv;
  475.     }
  476. }                /* xfmcontpts */
  477.  
  478.  
  479. /*----------------------------------------------------------------*/
  480. /* convert into DVI space and offset by H & V */
  481. static void 
  482. dvilinepts(x1, y1, x2, y2, offh, offv)
  483.     int32          *x1, *y1, *x2, *y2, offh, offv;
  484. {
  485.     *x1 += offh;
  486.     *x2 += offh;
  487.     *y1 = offv - *y1;
  488.     *y2 = offv - *y2;
  489. }
  490.  
  491.  
  492. /*----------------------------------------------------------------*/
  493. /* convert into DVI space and offset by H & V */
  494. static void 
  495. dvicontpts(xpts, xknots, offh, offv)
  496. int32(*xpts)[2];
  497.     int32           xknots, offh, offv;
  498. {
  499.     int32           i;
  500.  
  501.     for (i = 0; i <= xknots; i++)
  502.     {
  503.         xpts[i][0] += offh;
  504.         xpts[i][1] = offv - xpts[i][1];
  505.     }
  506. }
  507.  
  508.  
  509. /*----------------------------------------------------------------*/
  510. /*
  511.  * transform all the figure's elements according to the top-level tranformation requirements in 1st Quadrant space. then reset
  512.  * the toplevel's xfms.
  513.  */
  514. static void 
  515. toplevelxfm(toplev, curfig, recurlevel)
  516.     Item           *toplev, *curfig;
  517.     int32           recurlevel;
  518. {
  519.     Item           *pi;
  520.     ScaledPts       null1, null2, old1, old2, midx, midy;
  521.  
  522.     midy = (toplev->BBty - toplev->BBby) / 2;
  523.     midx = (toplev->BBrx - toplev->BBlx) / 2;
  524.     pi = curfig->UU.U8.body->things;    /* if recur==0, this is same as toplev */
  525.     while (pi != NULL)
  526.     {
  527.         switch (pi->kind)
  528.         {        /* with */
  529.  
  530.         case Aline:
  531.             xfmlinepts(&pi->UU.U1.lx1, &pi->UU.U1.ly1, &pi->UU.U1.lx2,
  532.                    &pi->UU.U1.ly2, 0, 0, midx, midy, 1.0,
  533.                    toplev->UU.U8.figtheta, toplev->UU.U8.fdx, toplev->UU.U8.fdy,
  534.                    toplev->UU.U8.fsx, toplev->UU.U8.fsy);
  535.             break;
  536.  
  537.         case Aspline:
  538.             xfmcontpts(pi->UU.U2.spts, pi->UU.U2.nsplknots, 0, 0, midx, midy, 1.0,
  539.                    toplev->UU.U8.figtheta, toplev->UU.U8.fdx, toplev->UU.U8.fdy,
  540.                    toplev->UU.U8.fsx, toplev->UU.U8.fsy);
  541.             break;
  542.  
  543.         case Attspline:
  544.             xfmcontpts(pi->UU.U3.ttpts, pi->UU.U3.nttknots, 0, 0, midx, midy, 1.0,
  545.                    toplev->UU.U8.figtheta, toplev->UU.U8.fdx, toplev->UU.U8.fdy,
  546.                    toplev->UU.U8.fsx, toplev->UU.U8.fsy);
  547.             break;
  548.  
  549.         case Aarc:
  550.             null1 = 0;
  551.             null2 = 0;
  552.             old1 = pi->UU.U6.acentx;
  553.             old2 = pi->UU.U6.acenty;
  554.             xfmlinepts(&pi->UU.U6.acentx, &pi->UU.U6.acenty, &null1, &null2, 0, 0,
  555.                    midx, midy, 1.0, toplev->UU.U8.figtheta, toplev->UU.U8.fdx,
  556.                    toplev->UU.U8.fdy, toplev->UU.U8.fsx, toplev->UU.U8.fsy);
  557.  
  558.             xfmcontpts(pi->UU.U6.arcpts, pi->UU.U6.narcknots + 1, 0, 0, old1,
  559.                    old2, 1.0, toplev->UU.U8.figtheta,
  560.                    toplev->UU.U8.fdx + pi->UU.U6.acentx - old1,
  561.                    toplev->UU.U8.fdy + pi->UU.U6.acenty - old2,
  562.                    toplev->UU.U8.fsx, toplev->UU.U8.fsy);
  563.             break;
  564.  
  565.         case Alabel:
  566.             null1 = 0;
  567.             null2 = 0;
  568.             xfmlinepts(&pi->UU.U7.labx, &pi->UU.U7.laby, &null1, &null2, 0, 0,
  569.                    midx, midy, 1.0, toplev->UU.U8.figtheta, toplev->UU.U8.fdx,
  570.                    toplev->UU.U8.fdy, toplev->UU.U8.fsx, toplev->UU.U8.fsy);
  571.             break;
  572.  
  573.         case Abeam:    /* not transformable */
  574.             break;
  575.  
  576.         case Atieslur:    /* not transformable */
  577.             break;
  578.  
  579.         case Afigure:
  580.             toplevelxfm(toplev, pi, recurlevel + 1);
  581.             break;
  582.         }        /* case */
  583.         pi = pi->nextitem;
  584.     }            /* while */
  585.     if (recurlevel != 0)    /* reset the toplevel's xfms */
  586.         return;
  587.     toplev->UU.U8.figtheta = 0.0;
  588.     toplev->UU.U8.fsx = 1.0;
  589.     toplev->UU.U8.fsy = 1.0;
  590.     toplev->UU.U8.fdx = 0;
  591.     toplev->UU.U8.fdy = 0;
  592. }
  593.  
  594.  
  595. /*----------------------------------------------------------------*/
  596. static double 
  597. scalefitfactor(actualwid, actualht, goalwid, goalht)
  598.     int32           actualwid, actualht, goalwid, goalht;
  599. {
  600.     double          sx, sy;
  601.  
  602.     sx = (double) goalwid / actualwid;
  603.     sy = (double) goalht / actualht;
  604.     if (sx < sy)
  605.         return sx;
  606.     else
  607.         return sy;
  608. }
  609.  
  610.  
  611.  
  612. /*
  613.  * ---- The handlers for each primitive ---- The result of calling each handler is either immediate output to the buffer of the
  614.  * commands to produce the primitive, OR the primitive gets pushed onto a stack/list that defines a current 'figure' (set of
  615.  * prims) for output at a later time
  616.  * 
  617.  * Look at linehandle for a basic idea of how the handlers work. the others follow pretty closely.
  618.  */
  619.  
  620.  
  621. /*------------------------------------------------------------*/
  622. void 
  623. linehandle(figdepth, scalefact, x1, y1, x2, y2, dvih, dviv, thk,
  624.        vk, patt, minx, maxx, miny, maxy, tx, ty, sx, sy, r)
  625.     int32           figdepth;
  626.     double          scalefact;
  627.     int32           x1, y1, x2, y2, dvih, dviv;
  628.     VThickness      thk;
  629.     VectKind        vk;
  630.     LineStyle       patt;
  631.     int32           minx, maxx, miny, maxy, tx, ty;
  632.     double          sx, sy, r;
  633. {
  634.     /* possible dvi-offsets */
  635.     ScaledPts       midx, midy;
  636.     Item           *lineitem;
  637.  
  638.     midx = (minx + maxx) / 2;
  639.     midy = (miny + maxy) / 2;
  640.  
  641.     /* do local primitive -level transformations */
  642.     xfmlinepts(&x1, &y1, &x2, &y2, dvih, dviv, midx, midy, scalefact, r, tx, ty,
  643.            sx, sy);
  644.  
  645.     if (figdepth == 0)
  646.     {            /* ---- do the primitive by itself */
  647.         /* re-transform it to the 4th Quadrant */
  648.         dvilinepts(&x1, &y1, &x2, &y2, h, v);    /* global h and v posit */
  649.         IPUSH();
  650.         TylLine(x1, y1, x2, y2, thk, vk, patt);
  651.         IPOP();
  652.         return;
  653.     }
  654.     if (figdepth <= 0)
  655.     {            /* ---- Pack it and stack it */
  656.         if (figdepth < 0)
  657.         {        /* ---- just do it right away without any PUSH/POP pair */
  658.             /*
  659.              * this is the case when we are unpacking a figure for immediate output
  660.              */
  661.             TylLine(x1, y1, x2, y2, thk, vk, patt);
  662.         }
  663.         return;
  664.     }
  665.     lineitem = NewItem(Aline);
  666.     lineitem->BBlx = minx;
  667.     lineitem->BBby = miny;
  668.     lineitem->BBrx = maxx;
  669.     lineitem->BBty = maxy;
  670.     lineitem->UU.U1.lx1 = x1;
  671.     lineitem->UU.U1.ly1 = y1;
  672.     lineitem->UU.U1.lx2 = x2;
  673.     lineitem->UU.U1.ly2 = y2;
  674.     lineitem->itemthick = thk;
  675.     lineitem->itemvec = (unsigned) vk;
  676.     lineitem->itempatt = (unsigned) patt;
  677.     pushItem(figdepth, lineitem);
  678. }                /* linehandle */
  679.  
  680.  
  681. /* ---   Simple Splines ----- */
  682. /*-----------------------------------------------------*/
  683. void 
  684. splinehandle(figdepth, scalefact, thetype, isclosed, markdiam,
  685.          contpts, nknots, dvih, dviv, thk, vec, patt, minx,
  686.          maxx, miny, maxy, tx, ty, sx, sy, r)
  687.     int32           figdepth;
  688.     double          scalefact;
  689.     SplineKind      thetype;
  690.     int        isclosed;
  691.     int32           markdiam;
  692. int32(*contpts)[2];
  693.     int32           nknots, dvih, dviv;
  694.     VThickness      thk;
  695.     VectKind        vec;
  696.     LineStyle       patt;
  697.     int32           minx, maxx, miny, maxy, tx, ty;
  698.     double          sx, sy, r;
  699. {
  700.     /* possible dvi-offsets */
  701.     ScaledPts       midx, midy;
  702.     Item           *splineitem;
  703.     int32           i;
  704.  
  705.     midx = (minx + maxx) / 2;
  706.     midy = (miny + maxy) / 2;
  707.  
  708.     xfmcontpts(contpts, nknots, dvih, dviv, midx, midy, scalefact, r, tx, ty,
  709.            sx, sy);
  710.  
  711.     if (figdepth == 0)
  712.     {            /* ----  do the primitive */
  713.         /* transform to 4th quad */
  714.         dvicontpts(contpts, nknots, h, v);
  715.         IPUSH();
  716.         TylSpline(thetype, isclosed, contpts, nknots, thk, vec, patt, markdiam);
  717.         IPOP();
  718.         return;
  719.     }
  720.     if (figdepth <= 0)
  721.     {
  722.         if (figdepth < 0)
  723.             TylSpline(thetype, isclosed, contpts, nknots, thk, vec, patt, markdiam);
  724.         return;
  725.     }
  726.     splineitem = NewItem(Aspline);
  727.     splineitem->BBlx = minx;
  728.     splineitem->BBby = miny;
  729.     splineitem->BBrx = maxx;
  730.     splineitem->BBty = maxy;
  731.     splineitem->itemthick = thk;
  732.     splineitem->itemvec = (unsigned) vec;
  733.     splineitem->itempatt = (unsigned) patt;
  734.     splineitem->UU.U2.nsplknots = nknots;
  735.     splineitem->UU.U2.spltype = (unsigned) thetype;
  736.     splineitem->UU.U2.sclosed = isclosed;
  737.     splineitem->UU.U2.dosmarks = markdiam;
  738.     for (i = 1; i <= nknots; i++)
  739.     {
  740.         splineitem->UU.U2.spts[i][0] = contpts[i][0];
  741.         splineitem->UU.U2.spts[i][1] = contpts[i][1];
  742.     }
  743.     pushItem(figdepth, splineitem);
  744. }                /* splinehandle */
  745.  
  746.  
  747. /* --- Variable thickness splines ----- */
  748. /*-----------------------------------------------------*/
  749. void 
  750. ttsplhandle(figdepth, scalefact, thetype, isclosed, markdiam,
  751.         contpts_, ttks_, nknots, dvih, dviv, vec, patt, minx,
  752.         maxx, miny, maxy, tx, ty, sx, sy, r)
  753.     int32           figdepth;
  754.     double          scalefact;
  755.     SplineKind      thetype;
  756.     int        isclosed;
  757.     int32           markdiam;
  758. int32(*contpts_)[2];
  759.     VThickness     *ttks_;
  760.     int32           nknots, dvih, dviv;
  761.     VectKind        vec;
  762.     LineStyle       patt;
  763.     int32           minx, maxx, miny, maxy, tx, ty;
  764.     double          sx, sy, r;
  765. {
  766.     /* possible dvi-offsets */
  767.     ControlPoints   contpts;
  768.     ThickAryType    ttks;
  769.     ScaledPts       midx, midy;
  770.     Item           *ttsplitem;
  771.     int32           i;
  772.     char        *memcpy PP((char *, char *, int));
  773.  
  774.     (void) memcpy((char *)contpts, (char *)contpts_, sizeof(ControlPoints));
  775.     (void) memcpy((char *)ttks, (char *)ttks_, sizeof(ThickAryType));
  776.     midx = (minx + maxx) / 2;
  777.     midy = (miny + maxy) / 2;
  778.  
  779.     xfmcontpts(contpts, nknots, dvih, dviv, midx, midy, scalefact, r, tx, ty,
  780.            sx, sy);
  781.  
  782.     if (figdepth == 0)
  783.     {
  784.         /* transform to 4th quad      */
  785.         dvicontpts(contpts, nknots, h, v);
  786.         IPUSH();
  787.         TylThickThinSpline(thetype, isclosed, contpts, ttks, nknots, vec, patt,
  788.                    markdiam);
  789.         IPOP();
  790.         return;
  791.     }
  792.  
  793.     if (figdepth <= 0)
  794.     {
  795.         if (figdepth < 0)
  796.             TylThickThinSpline(thetype, isclosed, contpts, ttks, nknots, vec, patt,
  797.                        markdiam);
  798.         return;
  799.     }
  800.     ttsplitem = NewItem(Attspline);
  801.     ttsplitem->BBlx = minx;
  802.     ttsplitem->BBby = miny;
  803.     ttsplitem->BBrx = maxx;
  804.     ttsplitem->BBty = maxy;
  805.     ttsplitem->itemvec = (unsigned) vec;
  806.     ttsplitem->itempatt = (unsigned) patt;
  807.     ttsplitem->UU.U3.nttknots = nknots;
  808.     ttsplitem->UU.U3.tspltype = (unsigned) thetype;
  809.     ttsplitem->UU.U3.dottmarks = markdiam;
  810.     ttsplitem->UU.U3.tclosed = isclosed;
  811.     for (i = 1; i <= nknots; i++)
  812.     {            /* ttsplitem */
  813.         ttsplitem->UU.U3.ttpts[i][0] = contpts[i][0];
  814.         ttsplitem->UU.U3.ttpts[i][1] = contpts[i][1];
  815.         ttsplitem->UU.U3.ttarry[i] = ttks[i];
  816.     }
  817.     pushItem(figdepth, ttsplitem);
  818. }                /* ttsplhandle */
  819.  
  820.  
  821. /* ---- Musical Beams ---- */
  822. /*-----------------------------------------------------*/
  823. void 
  824. beamhandle(depth, siz, bk, x1, y1, x2, y2)
  825.     int32           depth, siz;
  826.     BeamKind        bk;
  827.     int32           x1, y1, x2, y2;
  828. {
  829.     Item           *bmitem;
  830.  
  831.     if (depth == 0)
  832.     {
  833.         dvilinepts(&x1, &y1, &x2, &y2, h, v);
  834.         IPUSH();
  835.         TylBeam(x1, y1, x2, y2, siz, bk);
  836.         IPOP();
  837.         return;
  838.     }
  839.     if (depth <= 0)
  840.     {
  841.         if (depth < 0)
  842.         {
  843.             TylBeam(x1, y1, x2, y2, siz, bk);
  844.         }        /* else */
  845.         return;
  846.     }
  847.     bmitem = NewItem(Abeam);
  848.     bmitem->BBlx = min(x1, x2);
  849.     bmitem->BBby = min(y1, y2);
  850.     bmitem->BBrx = max(x1, x2);
  851.     bmitem->BBty = max(y1, y2);
  852.     bmitem->UU.U4.bx1 = x1;
  853.     bmitem->UU.U4.by1 = y1;
  854.     bmitem->UU.U4.bx2 = x2;
  855.     bmitem->UU.U4.by2 = y2;
  856.     bmitem->UU.U4.staf = siz;
  857.     bmitem->UU.U4.bkind = (unsigned) bk;    /* with */
  858.     pushItem(depth, bmitem);
  859. }                /* beamhandle */
  860.  
  861.  
  862. /* ---- Musical Ties and Slurs ----- */
  863. /*-----------------------------------------------------*/
  864. void 
  865. tieslurhandle(depth, pts_, numk, minthick, maxthick)
  866.     int32           depth;
  867. int32(*pts_)[2];
  868.     int32           numk;
  869.     VThickness      minthick, maxthick;
  870. {
  871.     ControlPoints   pts;
  872.     Item           *tsitem;
  873.     int32           i;
  874.     char        *memcpy PP((char *, char *, int));
  875.  
  876.     (void) memcpy((char *)pts, (char *)pts_, sizeof(ControlPoints));
  877.     if (depth == 0)
  878.     {
  879.         dvicontpts(pts, numk, h, v);
  880.         IPUSH();
  881.         TylTieSlur(pts, numk, minthick, maxthick);
  882.         IPOP();
  883.         return;
  884.     }
  885.     if (depth <= 0)
  886.     {
  887.         if (depth < 0)
  888.         {
  889.             TylTieSlur(pts, numk, minthick, maxthick);
  890.         }        /* else */
  891.         return;
  892.     }
  893.     tsitem = NewItem(Atieslur);
  894.     tsitem->UU.U5.ntknots = numk;
  895.     for (i = 1; i <= numk; i++)
  896.     {
  897.         tsitem->UU.U5.tspts[i][0] = pts[i][0];
  898.         tsitem->UU.U5.tspts[i][1] = pts[i][1];
  899.     }
  900.     tsitem->UU.U5.minth = minthick;
  901.     tsitem->UU.U5.maxth = maxthick;    /* with */
  902.     pushItem(depth, tsitem);
  903. }                /* tieslurhandle */
  904.  
  905.  
  906. /*---------------------------------------------------------*/
  907. void 
  908. arccirclehandle(figdepth, scalefact, cx, cy, radius, ang1, ang2,
  909.         contpts, nknots, dvih, dviv, thk, vec, patt, minx,
  910.         maxx, miny, maxy, tx, ty, sx, sy, r)
  911.     int32           figdepth;
  912.     double          scalefact;
  913.     int32           cx, cy, radius, ang1, ang2;
  914. int32(*contpts)[2];
  915.     int32           nknots, dvih, dviv;
  916.     VThickness      thk;
  917.     VectKind        vec;
  918.     LineStyle       patt;
  919.     int32           minx, maxx, miny, maxy, tx, ty;
  920.     double          sx, sy, r;
  921. {
  922.     /* IN */
  923.     /* possible dvi-offsets */
  924.     ScaledPts       midx, midy;
  925.     Item           *arcitem;
  926.     int32           i;
  927.     int        isclosedarc;
  928.  
  929.     midx = cx;
  930.     midy = cy;
  931.     isclosedarc = (ang1 == ang2);
  932.     /*
  933.      * if (isclosedarc) then maxspanlen := round ((360.0 / 16.0) * DEGTORAD * radius) else maxspanlen := round ((abs(ang2 -
  934.      * ang1) / 16.0) * DEGTORAD * radius); {
  935.      */
  936.  
  937.  
  938.     xfmcontpts(contpts, nknots + 1, dvih, dviv, midx, midy, scalefact, r, tx,
  939.            ty, sx, sy);
  940.  
  941.     if (figdepth == 0)
  942.     {            /* ---- just do the primitive */
  943.         /* transform to 4th quad */
  944.         dvicontpts(contpts, nknots + 1, h, v);
  945.         IPUSH();
  946.         doTylArc(isclosedarc, contpts, nknots, thk, vec, patt);
  947.         IPOP();
  948.         return;
  949.     }
  950.     if (figdepth <= 0)
  951.     {
  952.         if (figdepth < 0)
  953.             doTylArc(isclosedarc, contpts, nknots, thk, vec, patt);
  954.         return;
  955.     }
  956.     arcitem = NewItem(Aarc);
  957.     arcitem->BBlx = minx;
  958.     arcitem->BBby = miny;
  959.     arcitem->BBrx = maxx;
  960.     arcitem->BBty = maxy;
  961.     arcitem->itemthick = thk;
  962.     arcitem->itemvec = (unsigned) vec;
  963.     arcitem->itempatt = (unsigned) patt;
  964.     arcitem->UU.U6.narcknots = nknots;
  965.     arcitem->UU.U6.acentx = cx;
  966.     arcitem->UU.U6.acenty = cy;
  967.     arcitem->UU.U6.aradius = radius;
  968.     arcitem->UU.U6.firstang = ang1;
  969.     arcitem->UU.U6.lastang = ang2;
  970.     for (i = 0; i <= nknots + 1; i++)
  971.     {
  972.         arcitem->UU.U6.arcpts[i][0] = contpts[i][0];
  973.         arcitem->UU.U6.arcpts[i][1] = contpts[i][1];
  974.     }
  975.     pushItem(figdepth, arcitem);
  976. }                /* arccirclehandle */
  977.  
  978.  
  979.  
  980. /*---------------------------------------------------------*/
  981. void 
  982. labelhandle(depth, scalefact, lax, lay, dvih, dviv, style, phrase,
  983.         tx, ty)
  984.     int32           depth;
  985.     double          scalefact;
  986.     int32           lax, lay, dvih, dviv, style;
  987.     charstring      phrase;
  988.     int32           tx, ty;
  989. {
  990.     /* possible dvi-offsets */
  991.     Item           *labitem;
  992.     ScaledPts       null1, null2;
  993.  
  994.     /* xfm the label point if necessary */
  995.     lax += (int32) floor(tx * scalefact + 0.5);
  996.     lay += (int32) floor(ty * scalefact + 0.5);
  997.  
  998.     if (depth == 0)
  999.     {
  1000.         null1 = 0;
  1001.         null2 = 0;
  1002.         dvilinepts(&lax, &lay, &null1, &null2, h, v);
  1003.         IPUSH();
  1004.         TylLabel(lax, lay, style, phrase, strlen(phrase));
  1005.         IPOP();
  1006.         return;
  1007.     }
  1008.     if (depth <= 0)
  1009.     {
  1010.         if (depth < 0)
  1011.             TylLabel(lax, lay, style, phrase, strlen(phrase));
  1012.         return;
  1013.     }
  1014.     labitem = NewItem(Alabel);
  1015.     labitem->UU.U7.labx = lax;
  1016.     labitem->UU.U7.laby = lay;
  1017.     labitem->UU.U7.fontstyle = style;
  1018.     strcpy(labitem->UU.U7.labeltext, phrase);
  1019.     pushItem(depth, labitem);
  1020. }
  1021.  
  1022. /*
  1023.  * ####   Insert new handlers here for new "primitives" i.e., names callable from the \special[tyl ...]  level
  1024.  */
  1025.  
  1026. /*----------------------------------------------------------------*/
  1027. /* transform the current bbox coordinates, and output the new one */
  1028. static void 
  1029. newbbox(minx, maxx, miny, maxy, midx, midy, sx, sy, rot, tx, ty)
  1030.     int32          *minx, *maxx, *miny, *maxy, midx, midy;
  1031.     double          sx, sy, rot;
  1032.     int32           tx, ty;
  1033. {
  1034.     /* coords of full bbox for transformation [n/s][e/w][x/y] */
  1035.     ScaledPts       nex, ney, sex, sey, swx, swy, nwx, nwy;
  1036.     int32           temp1, temp2;
  1037.  
  1038.     /* describe  and transform the bbox */
  1039.     nwx = (int32) floor(*minx * sx + 0.5);
  1040.     nex = (int32) floor(*maxx * sx + 0.5);
  1041.     sex = (int32) floor(*maxx * sx + 0.5);
  1042.     swx = (int32) floor(*minx * sx + 0.5);
  1043.     ney = (int32) floor(*maxy * sy + 0.5);
  1044.     nwy = (int32) floor(*maxy * sy + 0.5);
  1045.     swy = (int32) floor(*miny * sy + 0.5);
  1046.     sey = (int32) floor(*miny * sy + 0.5);
  1047.  
  1048.     ptrotate(&nex, &ney, midx, midy, rot);
  1049.     ptrotate(&sex, &sey, midx, midy, rot);
  1050.     ptrotate(&swx, &swy, midx, midy, rot);
  1051.     ptrotate(&nwx, &nwy, midx, midy, rot);
  1052.  
  1053.     nex += tx;
  1054.     sex += tx;
  1055.     swx += tx;
  1056.     nwx += tx;
  1057.     ney += ty;
  1058.     sey += ty;
  1059.     swy += ty;
  1060.     nwy += ty;
  1061.     /* now find the actual extents of the bbox */
  1062.     temp1 = min(nex, nwx);
  1063.     temp2 = min(swx, sex);
  1064.     *minx = min(temp1, temp2);
  1065.  
  1066.     temp1 = min(ney, nwy);
  1067.     temp2 = min(swy, sey);
  1068.     *miny = min(temp1, temp2);
  1069.  
  1070.     temp1 = max(nex, nwx);
  1071.     temp2 = max(swx, sex);
  1072.     *maxx = max(temp1, temp2);
  1073.  
  1074.     temp1 = max(ney, nwy);
  1075.     temp2 = max(swy, sey);
  1076.     *maxy = max(temp1, temp2);
  1077. }
  1078.  
  1079.  
  1080. /*-----------------------------------------------*/
  1081. /*
  1082.  * find the bounding box of the list of primitives and/or sub-figures in this Item
  1083.  */
  1084.  
  1085. static void 
  1086. findBBox(blot, mnx, mxx, mny, mxy)
  1087.     Item           *blot;
  1088.     int32          *mnx, *mxx, *mny, *mxy;
  1089. {
  1090.     Item           *pi;
  1091.     ScaledPts       bmnx, bmxx, bmny, bmxy, midx, midy;    /* bbox [min/max][x/y] */
  1092.     ScaledPts       tmnx, tmxx, tmny, tmxy;    /* temporary, in case of recursion */
  1093.     ScaledPts       null1, null2, old1, old2;
  1094.     double          prescale, postscale;
  1095.  
  1096.     bmnx = TWO24;
  1097.     bmny = TWO24;
  1098.     bmxx = -TWO24;
  1099.     bmxy = -TWO24;
  1100.     if (blot->kind == Afigure)
  1101.     {            /* afigure */
  1102.         pi = blot->UU.U8.body->things;
  1103.         while (pi != NULL)
  1104.         {
  1105.             /* find the current bbox of the list of items here */
  1106.             if (pi->kind == Afigure)
  1107.             {    /* recur */
  1108.                 findBBox(pi, &tmnx, &tmxx, &tmny, &tmxy);
  1109.                 bmnx = min(bmnx, tmnx);
  1110.                 bmny = min(bmny, tmny);
  1111.                 bmxx = max(bmxx, tmxx);
  1112.                 bmxy = max(bmxy, tmxy);
  1113.             }
  1114.             else
  1115.             {
  1116.                 bmnx = min(bmnx, pi->BBlx);
  1117.                 bmny = min(bmny, pi->BBby);
  1118.                 bmxx = max(bmxx, pi->BBrx);
  1119.                 bmxy = max(bmxy, pi->BBty);
  1120.             }
  1121.             pi = pi->nextitem;
  1122.         }        /* while */
  1123.         /* now transform the items inside, AND the bbox */
  1124.         pi = blot->UU.U8.body->things;
  1125.         midx = (bmnx + bmxx) / 2;
  1126.         midy = (bmny + bmxy) / 2;
  1127.         /* now take care of any pre and post size requirements */
  1128.         /* see also the "figurehandle" proc. */
  1129.         /* #### Keep this scaling biz here, too, for now. May blast it later */
  1130.         if (blot->UU.U8.preWid != 0 && blot->UU.U8.preHt != 0)
  1131.         {
  1132.             prescale = scalefitfactor(bmxx - bmnx, bmxy - bmny, blot->UU.U8.preWid,
  1133.                           blot->UU.U8.preHt);
  1134.             blot->UU.U8.fsx *= prescale;
  1135.             blot->UU.U8.fsy *= prescale;
  1136.         }
  1137.         if (blot->UU.U8.postWid != 0 && blot->UU.U8.postHt != 0)
  1138.         {        /* with */
  1139.             postscale = scalefitfactor(bmxx - bmnx, bmxy - bmny,
  1140.                            blot->UU.U8.postWid, blot->UU.U8.postHt);
  1141.             blot->UU.U8.fsx *= postscale;
  1142.             blot->UU.U8.fsy *= postscale;
  1143.         }
  1144.  
  1145.         /* the actual scale-up is taken care of later in this proc. */
  1146.         while (pi != NULL)
  1147.         {
  1148.             switch (pi->kind)
  1149.             {    /* with */
  1150.  
  1151.             case Aline:
  1152.                 xfmlinepts(&pi->UU.U1.lx1, &pi->UU.U1.ly1, &pi->UU.U1.lx2,
  1153.                        &pi->UU.U1.ly2, 0, 0, midx, midy, 1.0,
  1154.                        blot->UU.U8.figtheta, blot->UU.U8.fdx, blot->UU.U8.fdy,
  1155.                        blot->UU.U8.fsx, blot->UU.U8.fsy);
  1156.                 break;
  1157.  
  1158.             case Aspline:
  1159.                 xfmcontpts(pi->UU.U2.spts, pi->UU.U2.nsplknots, 0, 0, midx, midy,
  1160.                        1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx,
  1161.                        blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy);
  1162.                 break;
  1163.  
  1164.             case Attspline:
  1165.                 xfmcontpts(pi->UU.U3.ttpts, pi->UU.U3.nttknots, 0, 0, midx, midy,
  1166.                        1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx,
  1167.                        blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy);
  1168.                 break;
  1169.  
  1170.             case Aarc:
  1171.                 null1 = 0;
  1172.                 null2 = 0;
  1173.                 old1 = pi->UU.U6.acentx;
  1174.                 old2 = pi->UU.U6.acenty;
  1175.                 xfmlinepts(&pi->UU.U6.acentx, &pi->UU.U6.acenty, &null1, &null2, 0,
  1176.                        0, midx, midy, 1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx,
  1177.                        blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy);
  1178.                 xfmcontpts(pi->UU.U6.arcpts, pi->UU.U6.narcknots + 1, 0, 0, old1,
  1179.                        old2, 1.0, blot->UU.U8.figtheta,
  1180.                        blot->UU.U8.fdx + pi->UU.U6.acentx - old1,
  1181.                        blot->UU.U8.fdy + pi->UU.U6.acenty - old2, blot->UU.U8.fsx,
  1182.                        blot->UU.U8.fsy);
  1183.                 break;
  1184.  
  1185.             case Alabel:
  1186.                 null1 = 0;
  1187.                 null2 = 0;
  1188.                 xfmlinepts(&pi->UU.U7.labx, &pi->UU.U7.laby, &null1, &null2, 0, 0,
  1189.                        midx, midy, 1.0, blot->UU.U8.figtheta, blot->UU.U8.fdx,
  1190.                        blot->UU.U8.fdy, blot->UU.U8.fsx, blot->UU.U8.fsy);
  1191.                 break;
  1192.  
  1193.             case Abeam:    /* not transformable */
  1194.                 break;
  1195.  
  1196.             case Atieslur:    /* not transformable */
  1197.                 break;
  1198.  
  1199.             case Afigure:    /* do not need to re-transform */
  1200.                 break;
  1201.             }    /* case */
  1202.             pi = pi->nextitem;
  1203.         }        /* while */
  1204.         /* transform the bbox, and re-find the new bbox */
  1205.         newbbox(&bmnx, &bmxx, &bmny, &bmxy, midx, midy, blot->UU.U8.fsx,
  1206.             blot->UU.U8.fsy, blot->UU.U8.figtheta, blot->UU.U8.fdx,
  1207.             blot->UU.U8.fdy);
  1208.         *mnx = bmnx;
  1209.         *mny = bmny;
  1210.         *mxx = bmxx;
  1211.         *mxy = bmxy;
  1212.         return;
  1213.     }            /* if */
  1214.     *mnx = blot->BBlx;
  1215.     *mny = blot->BBby;
  1216.     *mxx = blot->BBrx;
  1217.     *mxy = blot->BBty;
  1218.  
  1219.     /* some other primitive */
  1220.     /* else */
  1221. }                /* findBBox */
  1222.  
  1223.  
  1224. /*---------------------------------------------------------*/
  1225. /*
  1226.  * traverse the list, determining the current bounding box for the items. We need this to find the mid-point for doing any
  1227.  * remaining rotations
  1228.  */
  1229. static void 
  1230. traverse(thefig, theitem)
  1231.     Item           *thefig, *theitem;
  1232. {
  1233.     ScaledPts       minx, maxx, miny, maxy, curminx, curmaxx, curminy, curmaxy;
  1234.  
  1235.     minx = TWO24;
  1236.     maxx = -TWO24;
  1237.     miny = TWO24;
  1238.     maxy = -TWO24;
  1239.  
  1240.     while (theitem != NULL)
  1241.     {            /* set the bounding box for this upper-level symbol defn */
  1242.         if (theitem->kind == Afigure)
  1243.         {        /* recur */
  1244.             findBBox(theitem, &curminx, &curmaxx, &curminy, &curmaxy);
  1245.             theitem->BBlx = curminx;
  1246.             theitem->BBby = curminy;
  1247.             theitem->BBrx = curmaxx;
  1248.             theitem->BBty = curmaxy;
  1249.             /*
  1250.              * reset the symbol's parameters since all the primitives in it have now been transformed according to
  1251.              * the previous specifications
  1252.              */
  1253.             theitem->UU.U8.figtheta = 0.0;
  1254.             theitem->UU.U8.fsx = 1.0;
  1255.             theitem->UU.U8.fsy = 1.0;
  1256.             theitem->UU.U8.fdx = 0;
  1257.             theitem->UU.U8.fdy = 0;
  1258.             theitem->UU.U8.preWid = 0;
  1259.             theitem->UU.U8.preHt = 0;
  1260.             theitem->UU.U8.postWid = 0;
  1261.             theitem->UU.U8.postHt = 0;    /* with */
  1262.             minx = min(minx, curminx);
  1263.             miny = min(miny, curminy);
  1264.             maxx = max(maxx, curmaxx);
  1265.             maxy = max(maxy, curmaxy);
  1266.         }        /* if a figure/symbol */
  1267.         else
  1268.         {        /* a primitive */
  1269.             minx = min(minx, theitem->BBlx);
  1270.             miny = min(miny, theitem->BBby);
  1271.             maxx = max(maxx, theitem->BBrx);
  1272.             maxy = max(maxy, theitem->BBty);    /* with */
  1273.         }        /* else */
  1274.         theitem = theitem->nextitem;
  1275.     }            /* while */
  1276.  
  1277.     thefig->BBlx = minx;
  1278.     thefig->BBby = miny;
  1279.     thefig->BBrx = maxx;
  1280.     thefig->BBty = maxy;    /* with */
  1281. }                /* traverse */
  1282.  
  1283.  
  1284. #define DoItNow         (-1)
  1285. #define NoScale         1
  1286.  
  1287.  
  1288. /* ----- Figure symbols ----- */
  1289. /*---------------------------------------------------*/
  1290. void 
  1291. figurehandle(globalsymlist, symbollist, dopush)
  1292.     Item           *globalsymlist, *symbollist;
  1293.     int32           dopush;
  1294. {
  1295.     Item           *pi, *curfig;
  1296.     ScaledPts       midx, midy, null1, null2, tmnx, tmny, tmxx, tmxy;
  1297.     double          prescale, postscale;
  1298.  
  1299.     /*
  1300.      * PUSH. traverse the lists (recursively if necessary) and compute the transformed points. Convert to 4th quadrant and
  1301.      * offset by H & V. We can do this destructively here since we're going to output them right away anyhow. Then call
  1302.      * each respective primitive handler with a level of -1 to indicate  to do its job immediately. POP.
  1303.      */
  1304.     curfig = symbollist;
  1305.     pi = curfig->UU.U8.body->things;
  1306.     /*
  1307.      * find and set the bounding box for the figure's sub-symbols and primitives
  1308.      */
  1309.     if (dopush > 0)
  1310.         traverse(curfig, pi);
  1311.  
  1312.     /*
  1313.      * We eventually transform the items to 4th Quadrant DVI space and output them!
  1314.      */
  1315.  
  1316.     pi = curfig->UU.U8.body->things;
  1317.  
  1318.     midy = (globalsymlist->BBby + globalsymlist->BBty) / 2;
  1319.     midx = (globalsymlist->BBlx + globalsymlist->BBrx) / 2;
  1320.  
  1321.     if (dopush > 0)
  1322.     {            /* the top-level figure for outputting */
  1323.         /*
  1324.          * convert the bounding box because we are about to enter into DVI space, and all calls to handlers hereafter
  1325.          * are in terms of DVI coordinates
  1326.          */
  1327.  
  1328.  
  1329.         /*
  1330.          * Since there were external specifications about this figure, fit the current figure's actual size to the
  1331.          * "pre" size (specified by W marker) and/or to the "post" size (specified by the F marker). We do this by
  1332.          * simple scaling, *without* changing the midpoint of the bounding box, just its extents
  1333.          */
  1334.         if (globalsymlist->UU.U8.preWid != 0 && globalsymlist->UU.U8.preHt != 0)
  1335.         {
  1336.             prescale = scalefitfactor(globalsymlist->BBrx - globalsymlist->BBlx,
  1337.                           globalsymlist->BBty - globalsymlist->BBby,
  1338.                           globalsymlist->UU.U8.preWid, globalsymlist->UU.U8.preHt);
  1339.             globalsymlist->UU.U8.fsx *= prescale;
  1340.             globalsymlist->UU.U8.fsy *= prescale;
  1341.         }
  1342.         if (globalsymlist->UU.U8.postWid != 0 && globalsymlist->UU.U8.postHt != 0)
  1343.         {
  1344.             postscale = scalefitfactor(globalsymlist->BBrx - globalsymlist->BBlx,
  1345.                            globalsymlist->BBty - globalsymlist->BBby,
  1346.                            globalsymlist->UU.U8.postWid, globalsymlist->UU.U8.postHt);
  1347.             globalsymlist->UU.U8.fsx *= postscale;
  1348.             globalsymlist->UU.U8.fsy *= postscale;
  1349.         }
  1350.         tmnx = globalsymlist->BBlx;
  1351.         tmny = globalsymlist->BBby;
  1352.         tmxx = globalsymlist->BBrx;
  1353.         tmxy = globalsymlist->BBty;
  1354.         xfmlinepts(&tmnx, &tmny, &tmxx, &tmxy, 0, 0, midx, midy, 1.0, 0.0, 0,
  1355.                0, globalsymlist->UU.U8.fsx, globalsymlist->UU.U8.fsy);
  1356.  
  1357.         toplevelxfm(globalsymlist, globalsymlist, 0);
  1358.  
  1359.         dviBBlx = tmnx;
  1360.         dviBBrx = tmxx;
  1361.         dviBBby = tmny;
  1362.         dviBBty = tmxy;
  1363.  
  1364.         xfmlinepts(&dviBBlx, &dviBBby, &dviBBrx, &dviBBty, 0, 0, midx, midy,
  1365.                1.0, 0.0, globalsymlist->BBlx - tmnx,
  1366.                globalsymlist->BBby - tmny, 1.0, 1.0);
  1367.  
  1368.         globalsymlist->UU.U8.fdx += globalsymlist->BBlx - tmnx;
  1369.         globalsymlist->UU.U8.fdy += globalsymlist->BBby - tmny;
  1370.  
  1371.         dvilinepts(&dviBBlx, &dviBBby, &dviBBrx, &dviBBty, h, v);
  1372.         pgfigurenum++;
  1373.  
  1374.         /* We are ready to output the figure to the page */
  1375.         fprintf(logfile, "\nFigure #%ld on page %ld is approx. ",
  1376.             pgfigurenum, currpagenum);
  1377.         /*
  1378.          * write(logfile,((globalsymlist^.BBty - globalsymlist^.BBby) div SPPERPT):0,' pts high and ');
  1379.          * writeln(logfile,((globalsymlist^.BBrx - globalsymlist^.BBlx) div SPPERPT):0,' pts wide (actual size)');
  1380.          */
  1381.         fprintf(logfile, "%ld pts high and ", (tmxy - tmny) / SPPERPT);
  1382.         fprintf(logfile, "%ld pts wide (actual size)\n", (tmxx - tmnx) / SPPERPT);
  1383.         IPUSH();
  1384.  
  1385.     }
  1386.  
  1387.  
  1388.     while (pi != NULL)
  1389.     {
  1390.         switch (pi->kind)
  1391.         {        /* with */
  1392.  
  1393.         case Aline:
  1394.             dvilinepts(&pi->UU.U1.lx1, &pi->UU.U1.ly1, &pi->UU.U1.lx2,
  1395.                    &pi->UU.U1.ly2, h, v);
  1396.             /* DVI h and v posit */
  1397.             linehandle((int32) DoItNow, (double) NoScale, pi->UU.U1.lx1, pi->UU.U1.ly1,
  1398.                    pi->UU.U1.lx2, pi->UU.U1.ly2, 0, 0, pi->itemthick,
  1399.                    (VectKind) pi->itemvec, (LineStyle) pi->itempatt, dviBBlx,
  1400.                    dviBBrx, dviBBby, dviBBty, globalsymlist->UU.U8.fdx,
  1401.                    -globalsymlist->UU.U8.fdy, globalsymlist->UU.U8.fsx,
  1402.                    globalsymlist->UU.U8.fsy, -globalsymlist->UU.U8.figtheta);
  1403.             /*
  1404.              * p2c: x.p, line 4681: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
  1405.              */
  1406.             break;
  1407.             /* Aline */
  1408.  
  1409.         case Aspline:
  1410.             dvicontpts(pi->UU.U2.spts, pi->UU.U2.nsplknots, h, v);
  1411.             splinehandle((int32) DoItNow, (double) NoScale,
  1412.                      (SplineKind) pi->UU.U2.spltype, pi->UU.U2.sclosed,
  1413.                      pi->UU.U2.dosmarks, pi->UU.U2.spts, pi->UU.U2.nsplknots,
  1414.                      0, 0, pi->itemthick, (VectKind) pi->itemvec,
  1415.                      (LineStyle) pi->itempatt, dviBBlx, dviBBrx, dviBBby,
  1416.                      dviBBty, globalsymlist->UU.U8.fdx,
  1417.                      -globalsymlist->UU.U8.fdy, globalsymlist->UU.U8.fsx,
  1418.                      globalsymlist->UU.U8.fsy, -globalsymlist->UU.U8.figtheta);
  1419.             /*
  1420.              * p2c: x.p, line 4693: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
  1421.              */
  1422.             break;
  1423.             /* Aspline */
  1424.  
  1425.         case Attspline:
  1426.             dvicontpts(pi->UU.U3.ttpts, pi->UU.U3.nttknots, h, v);
  1427.             ttsplhandle((int32) DoItNow, (double) NoScale,
  1428.                     (SplineKind) pi->UU.U3.tspltype, pi->UU.U3.tclosed,
  1429.                     pi->UU.U3.dottmarks, pi->UU.U3.ttpts, pi->UU.U3.ttarry,
  1430.                     pi->UU.U3.nttknots, 0, 0, (VectKind) pi->itemvec,
  1431.                     (LineStyle) pi->itempatt, dviBBlx, dviBBrx, dviBBby, dviBBty,
  1432.                     globalsymlist->UU.U8.fdx, -globalsymlist->UU.U8.fdy,
  1433.                     globalsymlist->UU.U8.fsx, globalsymlist->UU.U8.fsy,
  1434.                     -globalsymlist->UU.U8.figtheta);
  1435.             /*
  1436.              * p2c: x.p, line 4705: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
  1437.              */
  1438.             break;
  1439.             /* Attspline */
  1440.  
  1441.         case Abeam:
  1442.             dvilinepts(&pi->UU.U4.bx1, &pi->UU.U4.by1, &pi->UU.U4.bx2,
  1443.                    &pi->UU.U4.by2, h, v);
  1444.             beamhandle((int32) DoItNow, pi->UU.U4.staf, (BeamKind) pi->UU.U4.bkind,
  1445.                    pi->UU.U4.bx1, pi->UU.U4.by1, pi->UU.U4.bx2, pi->UU.U4.by2);
  1446.             break;
  1447.             /* Abeam */
  1448.  
  1449.         case Atieslur:
  1450.             dvicontpts(pi->UU.U5.tspts, pi->UU.U5.ntknots, h, v);
  1451.             tieslurhandle((int32) DoItNow, pi->UU.U5.tspts, pi->UU.U5.ntknots,
  1452.                       pi->UU.U5.minth, pi->UU.U5.maxth);
  1453.             break;
  1454.             /* a tie or slur */
  1455.  
  1456.         case Aarc:
  1457.             dvicontpts(pi->UU.U6.arcpts, pi->UU.U6.narcknots + 1, h, v);
  1458.             arccirclehandle((int32) DoItNow, (double) NoScale, pi->UU.U6.acentx,
  1459.                     pi->UU.U6.acenty, pi->UU.U6.aradius, pi->UU.U6.firstang,
  1460.                     pi->UU.U6.lastang, pi->UU.U6.arcpts,
  1461.                     pi->UU.U6.narcknots, 0, 0, pi->itemthick,
  1462.                     (VectKind) pi->itemvec, (LineStyle) pi->itempatt, dviBBlx,
  1463.                     dviBBrx, dviBBby, dviBBty, globalsymlist->UU.U8.fdx,
  1464.                     -globalsymlist->UU.U8.fdy, globalsymlist->UU.U8.fsx,
  1465.                     globalsymlist->UU.U8.fsy,
  1466.                     -globalsymlist->UU.U8.figtheta);
  1467.             /*
  1468.              * p2c: x.p, line 4729: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
  1469.              */
  1470.             break;
  1471.             /* arc */
  1472.  
  1473.         case Alabel:
  1474.             null1 = 0;
  1475.             null2 = 0;
  1476.             dvilinepts(&pi->UU.U7.labx, &pi->UU.U7.laby, &null1, &null2, h, v);
  1477.             labelhandle((int32) DoItNow, (double) NoScale, pi->UU.U7.labx,
  1478.                     pi->UU.U7.laby, 0, 0, pi->UU.U7.fontstyle,
  1479.                     pi->UU.U7.labeltext, globalsymlist->UU.U8.fdx,
  1480.                     -globalsymlist->UU.U8.fdy);
  1481.             break;
  1482.             /* label */
  1483.  
  1484.         case Afigure:    /* recur */
  1485.             figurehandle(globalsymlist, pi, 0);
  1486.             break;
  1487.             /* another symbol */
  1488.  
  1489.         }        /* case */
  1490.         /*
  1491.          * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
  1492.          */
  1493.         /*
  1494.          * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
  1495.          */
  1496.         /*
  1497.          * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
  1498.          */
  1499.         /*
  1500.          * p2c: x.p, line 4747: Internal error in checkvarchangedexpr: Too few arguments for EK_FUNCTION [267]
  1501.          */
  1502.         pi = pi->nextitem;
  1503.     }            /* while */
  1504.     if (dopush > 0)
  1505.         IPOP();
  1506. }                /* figurehandle */
  1507.  
  1508. #undef DoItNow
  1509. #undef NoScale
  1510.